#include "print.h"
#include "config.h"
#include "pcb.h"
#include <stdio.h>
#include <stdlib.h>

static struct PCB **processes;

static int print_sep() {
  return printf("========================================\n");
}

static void print_state(proc_state s) {
  switch (s) {
  case WAITING:
    printf("W ");
    break;
  case RUNNING:
    printf("R ");
    break;
  case BLOCKED:
    printf("B ");
    break;
  case FINISH:
    printf("F ");
    break;
  }
}

static void print_processes() {

  print_sep();

  printf("ID\t\t\t");
  for (int i = 0; i < proc_count; ++i) {
    printf("%d ", processes[i]->pid);
  }
  printf("\n");

  printf("PRIORITY\t\t");
  for (int i = 0; i < proc_count; ++i) {
    printf("%d ", processes[i]->priority);
  }
  printf("\n");

  printf("CPUTIME\t\t\t");
  for (int i = 0; i < proc_count; ++i) {
    printf("%d ", processes[i]->cpu_time);
  }
  printf("\n");

  printf("ALLTIME\t\t\t");
  for (int i = 0; i < proc_count; ++i) {
    printf("%d ", processes[i]->cpu_time + processes[i]->need_time);
  }
  printf("\n");

  printf("STATE\t\t\t");
  for (int i = 0; i < proc_count; ++i) {
    print_state(processes[i]->state);
  }
  printf("\n");

  printf("NEXT\t\t\t");
  for (int i = 0; i < proc_count; ++i) {
    struct PCB *next = processes[i]->next;
    int next_pid = next ? next->pid : 0;
    printf("%d ", next_pid);
  }
  printf("\n");

  print_sep();
}

void init_print(struct PCB *head) {
  if (processes) {
    free_print();
  }

  processes = malloc(proc_count * sizeof(struct PCB *));
  for (; head; head = head->next) {
    processes[head->pid - 1] = head;
  }
}

void print_helper(int cpu_time, struct PCB *run, struct PCB *head) {
  printf("CPU TIME:%d \n", cpu_time);
  print_sep();
  printf("RUNNING PROC\t\tWAITING QUEUE\n");

  if (run) {
    printf("%d", run->pid);
  }
  printf("\t\t\t");
  for (; head && head->state == WAITING; head = head->next) {
    printf("%d ", head->pid);
  }
  printf("\n");
  print_processes();
  printf("\n");
}

void free_print() {
  free(processes);
  processes = NULL;
}

void print_init() {
  printf("PROCESSES INITIALIZED\n");
  print_processes();
  printf("START SCHEDULING\n\n----------------------------------------\n");
}